﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Windows.Forms;
using System.Xml;
using Assist;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using YArchitech.LIB;
using YArchitech.Revit;
using YArchitech.Revit.Electric.Common;
using HYElectricCommon;
using HYFamilyLibDataManager;
using HYRElectric.Equipment;
using TableTools;
using TableTools.DataDefine;

namespace HYRElectric.MaterialStatistics
{
	public class StatisticsItems
	{
		public StatisticsItems(ExternalCommandData cmdData)
		{
			this.cmdData = cmdData;
			this.ui_doc = cmdData.Application.ActiveUIDocument;
			string filename = HYElectricCommon.AssistFunc.GetAppRootPath() + "\\Data\\ElectricalData\\ElectricCategoryInfos.xml";
			try
			{
				this.xmlDoc.Load(filename);
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.ToString());
			}
			this.m_DBIndustry = FamilyLibDatabase.GetSqliteDB(SubjectType.Electric, cmdData.Application.Application.VersionNumber);
			this.m_XmlCategoryItemList = this.ReadXml();
		}

		public Result YJKExcute(ref string message, MaterialProgramInfos._Tag_TemplateType tag_TemplateType, bool isExcelTemp)
		{
			MaterialsStatisticsForm materialsStatisticsForm = new MaterialsStatisticsForm(this.cmdData, tag_TemplateType, isExcelTemp);
			List<ElementDate> list = new List<ElementDate>();
			if (materialsStatisticsForm.ShowDialog() != DialogResult.OK)
			{
				return Autodesk.Revit.UI.Result.Failed;
			}
			string text = "";
			List<string> list2 = new List<string>();
			List<CombinationOfAttributes> list3 = new List<CombinationOfAttributes>();
			List<MaterialProgramInfos.FilterType> list4 = new List<MaterialProgramInfos.FilterType>();
			TableInterface.GetStatisticsDetailsWithMaterialTable(SubjectType.Electric, this.cmdData, materialsStatisticsForm.selectName, materialsStatisticsForm.ProgramIdIndex, ref list2, ref list3, ref list4, ref text);
			if (list3.Count == 0)
			{
				message = "请设置属性对应关系";
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			if (materialsStatisticsForm.rdoConditionSet.Checked)
			{
				list.Clear();
				foreach (string categoryName in list2)
				{
					this.StatisticsItemsMethod(this.ui_doc.Document, categoryName, ref list);
				}
				if (list == null || list.Count == 0)
				{
					message = "请选择有效的区域！";
					return Autodesk.Revit.UI.Result.Cancelled;
				}
			}
			else if (materialsStatisticsForm.rdoViewSet.Checked)
			{
				if ((int)this.cmdData.Application.ActiveUIDocument.ActiveView.ViewType == 1)
				{
					list.Clear();
					IList<Element> selectFilterByRectangle = this.GetSelectFilterByRectangle(this.ui_doc);
					if (selectFilterByRectangle == null || selectFilterByRectangle.Count == 0)
					{
						message = "请选择有效的区域！";
						return Autodesk.Revit.UI.Result.Cancelled;
					}
					using (List<string>.Enumerator enumerator = list2.GetEnumerator())
					{
						while (enumerator.MoveNext())
						{
							string categoryName2 = enumerator.Current;
							if (selectFilterByRectangle != null)
							{
								this.GetViewSetFilterElem(categoryName2, selectFilterByRectangle, ref list);
							}
						}
						goto IL_179;
					}
				}
				message = "请切换到楼层平面视图下运行此命令进行选择！";
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			IL_179:
			ImportMaterialTableInfos importMaterialTableInfos = this.MaterialTableStatistics(list3, list);
			if (importMaterialTableInfos == null)
			{
				message = "选择的区域为空或没有数据！";
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			if (MaterialProgramInfos._Tag_TemplateType.TT_FAMILY.Equals(tag_TemplateType))
			{
				return TableInterface.DrawMaterialTable(this.cmdData, materialsStatisticsForm.selectName, materialsStatisticsForm.ProgramIdIndex, importMaterialTableInfos, ref message);
			}
			return TableInterface.ExportMaterialTable(this.cmdData, materialsStatisticsForm.selectName, materialsStatisticsForm.ProgramIdIndex, importMaterialTableInfos, ref message);
		}

		private void StatisticsItemsMethod(Autodesk.Revit.DB.Document doc, string categoryName, ref List<ElementDate> elementDateList)
		{
			ElementDate elementDate = new ElementDate();
			elementDate.TypeName = categoryName;
			elementDate.GetCalculateMode = this.GetCalculateModeByCategoryName(categoryName);
			int num = this.m_XmlCategoryItemList.FindIndex((XmlCategoryItems value) => value.Name.CompareTo(categoryName) == 0);
			if (num == -1)
			{
				throw new Exception("XML信息中未找到类别：" + categoryName + "！");
			}
			BuiltInCategory builtInCategory = this.m_XmlCategoryItemList[num].GetBuiltInCategory();
			elementDate.TypeElementItems = this.searchSystemObject<FamilyInstance>(doc, builtInCategory);
			elementDateList.Add(elementDate);
		}

		private void GetViewSetFilterElem(string categoryName, IList<Element> elementData, ref List<ElementDate> elementDateList)
		{
			List<Element> list = new List<Element>();
			ElementDate elementDate = new ElementDate();
			elementDate.TypeName = categoryName;
			elementDate.GetCalculateMode = this.GetCalculateModeByCategoryName(categoryName);
			int num = this.m_XmlCategoryItemList.FindIndex((XmlCategoryItems value) => value.Name.CompareTo(categoryName) == 0);
			if (num == -1)
			{
				throw new Exception("XML信息中未找到类别：" + categoryName + "！");
			}
			BuiltInCategory builtInCategory = this.m_XmlCategoryItemList[num].GetBuiltInCategory();
			foreach (Element element in elementData)
			{
                if ((int)builtInCategory == element.Category.GetHashCode())
				{
					list.Add(element);
				}
			}
			elementDate.TypeElementItems = list;
			elementDateList.Add(elementDate);
		}

		private StatisticsItems.CalculateMode GetCalculateModeByCategoryName(string categoryName)
		{
			if (categoryName.CompareTo("导线") == 0 || categoryName.CompareTo("桥架") == 0 || categoryName.CompareTo("线管") == 0)
			{
				return StatisticsItems.CalculateMode.CM_LINEAR;
			}
			if (categoryName.CompareTo("桥架配件") == 0 || categoryName.CompareTo("线管配件") == 0)
			{
				return StatisticsItems.CalculateMode.CM_NOLINEAR_Special;
			}
			return StatisticsItems.CalculateMode.CM_NOLINEAR;
		}

		private List<Element> searchSystemObject<T>(Autodesk.Revit.DB.Document doc, BuiltInCategory builtInCate)
		{
			List<Element> list = new List<Element>();
			foreach (Level level in Assist.AssistFunc.GetAllLevel(doc, StatisticsRange.Min, StatisticsRange.Max))
			{
				FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
				filteredElementCollector.OfClass(typeof(T));
				foreach (Element element in filteredElementCollector.OfCategory(builtInCate))
				{
					if (element != null)
					{
						try
						{
							if (element.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM) != null && element.get_Parameter(BuiltInParameter.FAMILY_LEVEL_PARAM).AsElementId() == level.Id)
							{
								list.Add(element);
							}
							else if (element.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM) != null && element.get_Parameter(BuiltInParameter.INSTANCE_SCHEDULE_ONLY_LEVEL_PARAM).AsElementId() == level.Id)
							{
								list.Add(element);
							}
							else if (element.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM) != null && element.get_Parameter(BuiltInParameter.RBS_START_LEVEL_PARAM).AsElementId() == level.Id)
							{
								list.Add(element);
							}
						}
						catch (Exception)
						{
						}
					}
				}
			}
			return list;
		}

		private ImportMaterialTableInfos MaterialTableStatistics(List<CombinationOfAttributes> combinationOfAttributesList, List<ElementDate> listStatisticsItems)
		{
			this.GetFamilyLegendFileInfo();
			DataSet dataSet = new DataSet();
			for (int i = 0; i < listStatisticsItems.Count; i++)
			{
				ElementDate ed = listStatisticsItems[i];
				CombinationOfAttributes combinationOfAtrributes = this.GetCombinationOfAtrributes(combinationOfAttributesList, ed);
				if (combinationOfAtrributes != null && combinationOfAtrributes.AttributesName != null)
				{
					DataTable dataTable = this.CreateDataTable(combinationOfAtrributes, ed);
					if (dataTable != null)
					{
						DataTable dataTable2 = this.StatisticsAmount(dataTable);
						if (dataTable2.Rows.Count > 0)
						{
							dataSet.Tables.Add(dataTable2);
						}
					}
				}
			}
			ImportMaterialTableInfos importMaterialTableInfos = new ImportMaterialTableInfos(SubjectType.Electric);
			int num = 0;
			if (dataSet.Tables.Count == 0)
			{
				return null;
			}
			foreach (object obj in dataSet.Tables)
			{
				DataTable dataTable3 = (DataTable)obj;
				for (int j = 0; j < dataTable3.Rows.Count; j++)
				{
					ImportTableRow row = null;
					List<ImportTableCell> list = new List<ImportTableCell>();
					for (int k = 0; k < dataTable3.Columns.Count; k++)
					{
						ImportTableCell item;
						if (dataTable3.Columns[k].ColumnName == "图例")
						{
							if (dataTable3.Rows[j]["图例类型"].ToString().Trim() == "1")
							{
								item = new ImportTableCell(_Tag_ImportCellValueType.CVT_LEGEND_NAME, dataTable3.Columns[k].ColumnName, dataTable3.Rows[j][k].ToString());
							}
							else
							{
								item = new ImportTableCell(_Tag_ImportCellValueType.CVT_SYSFAMILY_LEGEND_NAME, dataTable3.Columns[k].ColumnName, dataTable3.Rows[j][k].ToString());
							}
						}
						else if (dataTable3.Columns[k].ColumnName == "序号")
						{
							item = new ImportTableCell(_Tag_ImportCellValueType.CVT_STRING, dataTable3.Columns[k].ColumnName, (num + 1).ToString());
						}
						else if (dataTable3.Columns[k].ColumnName == "单位")
						{
							item = new ImportTableCell(_Tag_ImportCellValueType.CVT_STRING, dataTable3.Columns[k].ColumnName, dataTable3.Rows[j][k].ToString());
						}
						else
						{
							item = new ImportTableCell(_Tag_ImportCellValueType.CVT_STRING, dataTable3.Columns[k].ColumnName, dataTable3.Rows[j][k].ToString());
						}
						list.Add(item);
						row = new ImportTableRow(dataTable3.TableName, list);
					}
					importMaterialTableInfos.AddTableRecord(row);
					num++;
				}
			}
			return importMaterialTableInfos;
		}

		private CombinationOfAttributes GetCombinationOfAtrributes(List<CombinationOfAttributes> listCombin, ElementDate ed)
		{
			for (int i = 0; i < listCombin.Count; i++)
			{
				CombinationOfAttributes combinationOfAttributes = listCombin[i];
				if (combinationOfAttributes.CategoryName == ed.TypeName)
				{
					return combinationOfAttributes;
				}
			}
			return null;
		}

		private DataTable CreateDataTable(CombinationOfAttributes lvf, ElementDate ed)
		{
			DataTable dataTable = new DataTable(lvf.CategoryName);
			if (lvf.AttributesName == null)
			{
				return null;
			}
			foreach (string text in lvf.AttributesName)
			{
				if (!dataTable.Columns.Contains(text))
				{
					dataTable.Columns.Add(text);
				}
			}
			for (int i = 0; i < ed.TypeElementItems.Count; i++)
			{
				DataRow row = dataTable.NewRow();
				dataTable.Rows.Add(row);
			}
			dataTable.Columns.Add("序号");
			dataTable.Columns.Add("图例类型");
			dataTable.Columns.Add("数量长度");
			dataTable.Columns.Add("单位");
			dataTable.Columns.Add("图例");
			foreach (string text2 in lvf.AttributesName)
			{
				XmlAttributeData attributeData = this.GetAttributeData(this.m_XmlCategoryItemList, ed.TypeName, text2);
				int num = 0;
				DbFamily dbFamily = null;
				for (int j = 0; j < ed.TypeElementItems.Count; j++)
				{
					Element element = ed.TypeElementItems[j];
					dataTable.Rows[j][text2] = this.GetElementParameterStr(element, attributeData);
					if (ed.GetCalculateMode == StatisticsItems.CalculateMode.CM_LINEAR)
					{
						dataTable.Rows[j]["数量长度"] = this.GetLinearEquipmentlenth(element);
						dataTable.Rows[j]["单位"] = "米";
						string name = element.Category.Name;
						dataTable.Rows[j]["图例"] = this.GetLegendFileFillNameByFamilyName(name);
						dataTable.Rows[j]["图例类型"] = "0";
					}
					else if (ed.GetCalculateMode == StatisticsItems.CalculateMode.CM_NOLINEAR)
					{
						dataTable.Rows[j]["数量长度"] = 1;
						dataTable.Rows[j]["单位"] = "个";
						string text3 = (element as FamilyInstance).Symbol.Family.Name;
						text3 = text3.Replace("HY_", "");
						dataTable.Rows[j]["图例"] = this.GetLegendFileFillNameByFamilyName(text3);
						dataTable.Rows[j]["图例类型"] = "1";
					}
					else
					{
						dataTable.Rows[j]["数量长度"] = 1;
						dataTable.Rows[j]["单位"] = "个";
						FamilyInstance familyInstance = element as FamilyInstance;
						if (familyInstance != null)
						{
							string name2 = familyInstance.Symbol.Family.Name;
							if (num == 0)
							{
								if (this.m_DBIndustry == null)
								{
									goto IL_3C9;
								}
								dbFamily = this.m_DBIndustry.FamilyTable[name2];
								num++;
							}
							if (dbFamily == null)
							{
								string name3 = familyInstance.Category.Name;
								dataTable.Rows[j]["图例"] = this.GetLegendFileFillNameByFamilyName(name3);
								dataTable.Rows[j]["图例类型"] = "0";
							}
							else
							{
								string text4 = familyInstance.Symbol.Family.Name;
								text4 = text4.Replace("HY_", "");
								dataTable.Rows[j]["图例"] = this.GetLegendFileFillNameByFamilyName(text4);
								dataTable.Rows[j]["图例类型"] = "1";
							}
						}
					}
					IL_3C9:;
				}
			}
			return dataTable;
		}

		private IList<Element> GetSelectFilterByRectangle(UIDocument rvt_UIdoc)
		{
			IList<Element> result;
			try
			{
				IList<Element> list = rvt_UIdoc.Selection.PickElementsByRectangle("请选择需要统计的区域");
				if (list == null || list.Count == 0)
				{
					result = null;
				}
				else
				{
					result = list;
				}
			}
			catch (Autodesk.Revit.Exceptions.OperationCanceledException)
			{
				result = null;
			}
			catch (Exception ex)
			{
				ex.Message.ToString();
				result = null;
			}
			return result;
		}

		private string GetLegendFileFillNameByFamilyName(string familyName)
		{
			if (this.m_FamilyLengendDictionary.ContainsKey(familyName))
			{
				return this.m_FamilyLengendDictionary[familyName];
			}
			return Product.InstallLocation + "\\EquipmentImage\\ElectricLegend\\" + familyName + ".png";
		}

		private void GetFamilyLegendFileInfo()
		{
			foreach (string tableName in TableName.AllTableName())
			{
				List<DbFamilyObject> list = new FamilyLibDataAssist(this.ui_doc.Document, tableName).LoadFamilyDatas(null);
				try
				{
					foreach (DbFamilyObject dbFamilyObject in list)
					{
						if (!string.IsNullOrEmpty(dbFamilyObject.Image2D))
						{
							string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(dbFamilyObject.Family);
							if (!this.m_FamilyLengendDictionary.ContainsKey(fileNameWithoutExtension))
							{
								this.m_FamilyLengendDictionary.Add(fileNameWithoutExtension, dbFamilyObject.Image2D);
							}
						}
					}
				}
				catch (Exception)
				{
				}
			}
		}

		private double GetLinearEquipmentlenth(Element elem)
		{
			double num;
			if (elem is Wire)
			{
				Wire wire = elem as Wire;
				ConnectorSet connectors = wire.ConnectorManager.Connectors;
				if (connectors.Size != 2)
				{
					throw new Exception("导线连接数错误！");
				}
				ConnectorSetIterator connectorSetIterator = connectors.ForwardIterator();
				connectorSetIterator.MoveNext();
				Connector connector = connectorSetIterator.Current as Connector;
				connectorSetIterator.MoveNext();
				Connector connector2 = connectorSetIterator.Current as Connector;
				Connector nativeConnector = this.GetNativeConnector(wire.Id, connector);
				Connector nativeConnector2 = this.GetNativeConnector(wire.Id, connector2);
				XYZ xyz = new XYZ(connector.Origin.X, connector.Origin.Y, 0.0);
				XYZ xyz2 = new XYZ(connector2.Origin.X, connector2.Origin.Y, 0.0);
				num = xyz.DistanceTo(xyz2);
				double num2 = 0.0;
				if (this.WireRealElevation(wire, ref num2))
				{
					if (nativeConnector != null)
					{
						num += Math.Abs(nativeConnector.Origin.Z - num2);
					}
					if (nativeConnector2 != null)
					{
						num += Math.Abs(nativeConnector2.Origin.Z - num2);
					}
				}
				num = Assist.AssistFunc.feetToMM(num) / 1000.0;
				num = Math.Round(num, 2);
			}
			else
			{
				num = Assist.AssistFunc.feetToMM((elem.Location as LocationCurve).Curve.Length) / 1000.0;
				num = Math.Round(num, 2);
			}
			return num;
		}

		private bool WireRealElevation(Wire wire, ref double wireElevation)
		{
			Parameter parameter = wire.GetParameter("相对标高");
			if (parameter != null && parameter.HasValue)
			{
				string text = parameter.AsDouble().ToString("f0");
				if (text.CompareTo("") != 0)
				{
					try
					{
						wireElevation = Assist.AssistFunc.mmToFeet(Convert.ToDouble(text) * 1000.0);
						return true;
					}
					catch (Exception)
					{
						return false;
					}
					return false;
				}
			}
			return false;
		}

		private Connector GetNativeConnector(ElementId ownerId, Connector connector)
		{
			ConnectorSetIterator connectorSetIterator = connector.AllRefs.ForwardIterator();
			while (connectorSetIterator.MoveNext())
			{
				object obj = connectorSetIterator.Current;
				Connector connector2 = obj as Connector;
				if (connector2.Owner.Id.IntegerValue != ownerId.IntegerValue)
				{
					return connector2;
				}
			}
			return null;
		}

		private string GetElementParameterStr(Element elem, XmlAttributeData attributeData)
		{
			try
			{
				Parameter parameter = attributeData.GetParameter(elem);
				if (parameter == null)
				{
					return "";
				}
				if ((int)parameter.StorageType == 3)
				{
					return parameter.AsString();
				}
				return parameter.AsValueString();
			}
			catch (Exception)
			{
			}
			return "";
		}

		private DataTable StatisticsAmount(DataTable dt)
		{
			DataTable dataTable = dt.Clone();
			foreach (object obj in dt.Rows)
			{
				DataRow dataRow = (DataRow)obj;
				string text = null;
				for (int i = 0; i < dt.Columns.Count; i++)
				{
					string columnName = dt.Columns[i].ColumnName;
					if (columnName != null && columnName != "" && dataRow[columnName].ToString().Trim() != "" && columnName != "数量长度")
					{
						text = string.Concat(new string[]
						{
							text,
							columnName.ToString().Trim(),
							"='",
							dataRow[columnName].ToString().Trim(),
							"' and "
						});
					}
				}
				try
				{
					if (text.Length > 5)
					{
						text = text.Substring(0, text.Length - 5);
					}
				}
				catch (Exception)
				{
				}
				if (text != null)
				{
					DataRow[] array = dataTable.Select(text);
					if (array.Length != 0)
					{
						try
						{
							if (array[0].Table.Columns.Contains("数量长度"))
							{
								array[0]["数量长度"] = Convert.ToDecimal(array[0]["数量长度"]) + Convert.ToDecimal(dataRow["数量长度"]);
							}
							continue;
						}
						catch (Exception)
						{
							continue;
						}
					}
					dataTable.ImportRow(dataRow);
				}
			}
			return dataTable;
		}

		private XmlAttributeData GetAttributeData(List<XmlCategoryItems> xi, string catagoris, string propertyType)
		{
			foreach (XmlCategoryItems xmlCategoryItems in xi)
			{
				if (xmlCategoryItems.Name == catagoris)
				{
					foreach (XmlAttributeData xmlAttributeData in xmlCategoryItems.XmlItem)
					{
						if (xmlAttributeData.Title == propertyType)
						{
							return xmlAttributeData;
						}
					}
				}
			}
			return null;
		}

		private List<XmlCategoryItems> ReadXml()
		{
			XmlNode xmlNode = this.xmlDoc.SelectSingleNode("/Root/Categories");
			List<XmlCategoryItems> list = new List<XmlCategoryItems>();
			foreach (object obj in xmlNode)
			{
				XmlElement xmlElement = (XmlElement)obj;
				XmlCategoryItems xmlCategoryItems = new XmlCategoryItems();
				xmlCategoryItems.Name = xmlElement.GetAttribute("Name");
				xmlCategoryItems.StrBuiltInCategory = xmlElement.GetAttribute("BuiltInCategory");
				xmlCategoryItems.Unit = xmlElement.GetAttribute("Unit");
				List<XmlAttributeData> list2 = new List<XmlAttributeData>();
				foreach (object obj2 in xmlElement)
				{
					XmlElement xmlElement2 = (XmlElement)obj2;
					list2.Add(new XmlAttributeData
					{
						Title = xmlElement2.GetAttribute("Title"),
						Name = xmlElement2.GetAttribute("Name"),
						StrBuiltInParameter = xmlElement2.GetAttribute("BuiltInParameter")
					});
				}
				xmlCategoryItems.XmlItem = list2;
				list.Add(xmlCategoryItems);
			}
			return list;
		}

		private const string _EQUIPMENTNUM = "数量长度";

		private const string LEGENDNAME = "图例";

		private const string SEQUENCENUM = "序号";

		private const string LEGENDTYPE = "图例类型";

		private const string LEGENDVALUE = "1";

		private const string UINTATTRIBUTE = "单位";

		private const string KILLMITFEET = "米";

		private const string NUMCOUNT = "个";

		private const string SYSTEMTYPE = "0";

		private const string NOSYSTEMTYPE = "1";

		private List<XmlCategoryItems> m_XmlCategoryItemList;

		private FamilyLibDatabase m_DBIndustry;

		private ExternalCommandData cmdData;

		private UIDocument ui_doc;

		private XmlDocument xmlDoc = new XmlDocument();

		private Dictionary<string, string> m_FamilyLengendDictionary = new Dictionary<string, string>();

		public enum CalculateMode
		{
			CM_LINEAR,
			CM_NOLINEAR,
			CM_NOLINEAR_Special
		}
	}
}
